<?php

/* ========================================================================= */
/* This file is part of the HypnoPHP Framework Library                       */
/* Copyright (c) 2009-2010, Radu Buzea                                       */
/* ========================================================================= */

/**
* @author Radu Buzea
* @copyright Copyright (c) 2009-2010, Radu Buzea (www.hypnosis.ro)
* @license GNU Lesser General Public License (www.gnu.org/copyleft/lesser.html)
* @package HypnoPHP
* @category Core
* @version 1.0.3
*/

// ============================================================================
// Final class: HFileSys
// ============================================================================


final class HFileSys
{

	# ###########################################################################

	/**
	* Create nested directories
	*
	*/
	static public function mkdir($dir_path = '', $chmod = 0777)
	{
		$dir_path = trim($dir_path);
		if ($dir_path == '') {
			return false;
		}
		$separator = DS;
		if ($separator == "/") {
			$dir_path = str_replace("\\",  $separator, $dir_path);
		} else {
			$dir_path = str_replace("/", $separator, $dir_path);
		}
		$dir_parts = explode(DS, $dir_path);
		$new_dirs = array();
		$dir_name = "";
		foreach ($dir_parts as $dir) {
			$dir_name = $dir_name ? $dir_name . DS . $dir : $dir;
			if (!is_dir($dir_name)) {
				$new_dirs[] = $dir_name;
			}
		}
		$old_umask = umask(0);
		$result = mkdir($dir_path, $chmod, true);
		if ($result) {
			foreach ($new_dirs as $dir) {
				chmod($dir, $chmod);
			}
		}
		umask($old_umask);
		return $result;
	}

	# ###########################################################################

	/**
	* Check a file or a directory
	*
	* @param string $file_name The file or directory name (with or without path)
	* @param string $attr_checks Check by file or directory attributes
	* add 'D' for directory check, 'R' for readable check, 'W' for writable check
	* (example 'DRW', 'RW', 'R')
	* @return bool
	*/
	static public function checkFile($file_name = '', $attr_checks = '')
	{
		$file_name = trim($file_name);
		if ($file_name == '') {
			return false;
		}
		$file_is_ok = false;
		$file_exists = false;

		$attr_checks = trim(strtoupper($attr_checks));
		$check_dir = (strpos($attr_checks, 'D') !== false);
		$check_readable = (strpos($attr_checks, 'R') !== false);
		$check_writable = (strpos($attr_checks, 'W') !== false);

		$check_path = dirname($file_name);
		if ($check_path != '.' && $check_path != DS && is_dir($check_path)) {
			if (($check_dir && is_dir($file_name)) || (!$check_dir && is_file($file_name))) {
				$file_exists = true;
				$file_is_ok = ($check_readable && is_readable($file_name)) ||
					($check_writable && is_writable($file_name)) ||
					(!$check_readable && !$check_writable);
			} else {
				$file_is_ok = true;
			}
		} else {
			global $_HAPPLICATION_PATHS;
			if (isset($_HAPPLICATION_PATHS['app_cache'])) {
				$cache_path = $_HAPPLICATION_PATHS['app_cache'];
			} else if (defined('HAPPLICATION_PATH')) {
				$cache_path = defined('HAPPLICATION_PATH') . DS . 'cache';
			}
			if (!isset($cache_path)) {
				trigger_error("Unknown cache directory", E_USER_WARNING);
				return false;
			} else if(!is_dir($cache_path)) {
				trigger_error("Invalid cache directory <i>$cache_path</i>", E_USER_WARNING);
				return false;
			}
			$file_name = $cache_path . DS . $file_name;
			if (($check_dir && is_dir($file_name)) || (!$check_dir && is_file($file_name))) {
				$file_exists = true;
				$file_is_ok = ($check_readable && is_readable($file_name)) ||
					($check_writable && is_writable($file_name)) ||
					(!$check_readable && !$check_writable);
			}
			if (!$file_is_ok && $file_name != '' && is_dir(dirname($file_name)) &&
				is_writable(dirname($file_name))) {
					$file_is_ok = true;
				}
		}
		if (!$file_is_ok) {
			if ($file_exists) {
				if ($check_dir) {
					trigger_error("Invalid directory name <i>$file_name</i>", E_USER_WARNING);
				} else {
					trigger_error("Invalid file name <i>$file_name</i>", E_USER_WARNING);
				}
			} else {
				$msg = '';
				if ($check_readable) {
					$msg .= 'readable';
				}
				if ($check_writable) {
					if ($msg != '') {
						$msg .= ' and ';
					}
					$msg .= 'writable';
				}
				if ($check_dir) {
					trigger_error("The directory <i>$file_name</i> is not $msg", E_USER_WARNING);
				} else {
					trigger_error("The file <i>$file_name</i> is not $msg", E_USER_WARNING);
				}
			}
			return false;
		}
		return $file_name;
	}

	# ###########################################################################

	/**
	* Write a file (local file system)
	*
	* @param string $data The file content
	* @param string $file_name The file name
	* @return bool
	*/
	static public function writeFile($data = null, $file_name = '')
	{
		$file_name = self::checkFile($file_name, 'W');
		if ($file_name === false) {
			return false;
		}
		if (file_exists($file_name)){
			if (is_dir($file_name)) {
				trigger_error("<i>$file_name</i> is a directory", E_USER_WARNING);
				return false;
			}
			if (!is_writable($file_name)) {
				trigger_error("The file <i>$file_name</i> is not writable", E_USER_WARNING);
				return false;
			}
			unlink($file_name);
		}
		$dir_name = dirname($file_name);
		if (!is_dir($dir_name)) {
			trigger_error("The directory <i>$dir_name</i> not exists", E_USER_WARNING);
			return false;
		}
		if (!is_writable($dir_name)) {
			trigger_error("The directory <i>$dir_name</i> is not writable", E_USER_WARNING);
			return false;
		}
		if (is_null($data) || !is_string($data)) {
			$data = '';
		}

		$fhandle = fopen($file_name, "x");
		if ($fhandle) {
			$fwrite_result = fwrite($fhandle, $data, strlen($data));
			fclose($fhandle);
			if ($fwrite_result === false) {
				trigger_error("Cannot write data in file <i>$file_name</i>", E_USER_WARNING);
			} else {
				return true;
			}
		} else {
			trigger_error("Cannot open or create file <i>$file_name</i>", E_USER_WARNING);
		}
		return false;
	}

	# ###########################################################################

	/**
	* Read the entire content from a file (local file system)
	*
	* @param string $data The file content
	* @param string $file_name The file name
	* @return bool
	*/
	static public function readFile($file_name = '')
	{
		$file_name = self::checkFile($file_name, 'R');
		if ($file_name === false) {
			return false;
		}
		if (!is_file($file_name)) {
			trigger_error("<i>$file_name</i> is a directory", E_USER_WARNING);
			return false;
		}
		return file_get_contents($file_name);
	}

	# ###########################################################################

}
